

use ggez::graphics::StrokeOptions;
use ggez::{Context, GameResult, GameError, graphics};
use ggez::mint::Point2;
use noise::{NoiseFn, Perlin};

const UX: Point2<f32> = Point2{x: -40.0, y: 10.0};
const UY: Point2<f32> = Point2{x: 40.0, y: 10.0};
const UZ: Point2<f32> = Point2{x: 0.0, y: -640.0};
const ZERO_PIVOT: Point2<f32> = Point2{x:400.0, y: 500.0};
pub struct State{
    t: f64,
    perlin: Perlin,
    data: Vec<Point2<f32>>,

}

impl State{
    pub fn new() -> State {
        State{t: 0.0, perlin: Perlin::new(0), data: vec![]}
    }
}

impl ggez::event::EventHandler<GameError> for State {
    fn update(&mut self, _ctx: &mut Context) -> GameResult {
        self.data.clear();
        for tx in 0..10 {
            for ty in 0..10 {
                let tz = self.perlin.get([(tx as f64)*0.05, (ty as f64)*0.05, self.t])*0.5+0.5;
                let x = ZERO_PIVOT.x + UX.x*(tx as f32) + UY.x*(ty as f32) + UZ.x*(tz as f32);
                let y = ZERO_PIVOT.y + UX.y*(tx as f32) + UY.y*(ty as f32) + UZ.y*(tz as f32);
                self.data.push(Point2 { x: x, y: y });
            }
        }
        self.t += 0.05;
        Ok(())
    }
    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        let mut canvas = graphics::Canvas::from_frame(ctx, graphics::Color::WHITE);

        for i in 0..9 {
            for j in 0..9 {
                let c =  {
                    if self.data[i*10+j].y>self.data[(i+1)*10+j+1].y {
                        -(self.data[(i+1)*10+j+1].y-self.data[i*10+j].y)/100.0
                    } else {
                        (self.data[(i+1)*10+j+1].y-self.data[i*10+j].y)/50.0
                    }
                };
                let rect1 = graphics::Mesh::new_polygon(
                    ctx,
                    graphics::DrawMode::fill(),
                    &[self.data[i*10+j], self.data[(i+1)*10+j], self.data[(i+1)*10+j+1], self.data[i*10+j+1]],
                    graphics::Color::new(c, c, c, 1.0),
                )?;
                canvas.draw(&rect1, graphics::DrawParam::default());
                let rect = graphics::Mesh::new_polygon(
                    ctx,
                    graphics::DrawMode::Stroke(StrokeOptions::DEFAULT),
                    &[self.data[i*10+j], self.data[(i+1)*10+j], self.data[(i+1)*10+j+1], self.data[i*10+j+1]],
                    graphics::Color::new(0.0, 0.0, 0.0, 1.0),
                )?;
                canvas.draw(&rect, graphics::DrawParam::default());
            }
        }
        canvas.finish(ctx)?;
        Ok(())
    }
}